package com.vip8.recorder.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.vip8.recorder.api.model.dto.UserDTO;
import com.vip8.recorder.api.model.dto.VerificationCodeDTO;
import com.vip8.recorder.api.model.params.UserParams;
import com.vip8.recorder.service.constant.OnlineStatus;
import com.vip8.recorder.service.db.mapper.UserInfoDao;
import com.vip8.recorder.service.db.mapper.VerificationCodeDao;
import com.vip8.recorder.service.db.model.UserInfo;
import com.vip8.recorder.service.db.model.UserInfoExample;
import com.vip8.recorder.service.db.model.VerificationCode;
import com.vip8.recorder.service.db.model.VerificationCodeExample;
import com.vip8.recorder.service.service.SmsService;
import com.vip8.recorder.service.service.UserService;
import com.vip8.recorder.service.utils.*;
import com.vip8.recorder.service.utils.yonghui.FetchAuthCode;
import com.vip8.recorder.service.utils.yonghui.YhUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    private VerificationCodeDao codeDao;
    @Resource
    private SmsService smsService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public VerificationCodeDTO generateCode(String countryCode, String phone) throws Exception {
        if (!MobileValidator.isValidChineseMobileNumber(phone)) {
            throw new RuntimeException("手机号不合法!");
        }
        VerificationCodeExample example = new VerificationCodeExample();
        VerificationCodeExample.Criteria criteria = example.createCriteria();
        if (StringUtil.isEmpty(countryCode)) {
            criteria.andCountryCodeEqualTo(countryCode);
        }
        criteria.andPhoneEqualTo(phone);
        criteria.andExpirationGreaterThan(DateUtils.addMinutes(new Date(), 4));

        List<VerificationCode> codes = codeDao.selectByExample(example);
        if (CollectionUtil.isNotEmpty(codes)) {
            throw new RuntimeException("请勿频繁操作");
        }

        String randomCode = genCode(4);
        VerificationCode verificationCode = new VerificationCode();
        verificationCode.setCode(randomCode);
        verificationCode.setCountryCode(countryCode);
        verificationCode.setPhone(phone);
        verificationCode.setExpiration(DateUtils.addMinutes(new Date(), 5));
        codeDao.insertSelective(verificationCode);
        VerificationCodeDTO codeDTO = new VerificationCodeDTO();
        BeanCopyUtil.copyBean(verificationCode, codeDTO);

        smsService.sendSms(phone, randomCode);
        return codeDTO;
    }

    @Override
    public VerificationCodeDTO getCode(String countryCode, String phone) {
        if (!MobileValidator.isValidChineseMobileNumber(phone)) {
            throw new RuntimeException("手机号不合法!");
        }
        VerificationCodeExample example = new VerificationCodeExample();
        VerificationCodeExample.Criteria criteria = example.createCriteria();
        if (StringUtil.isEmpty(countryCode)) {
            criteria.andCountryCodeEqualTo(countryCode);
        }
        criteria.andPhoneEqualTo(phone);
        criteria.andExpirationGreaterThan(DateUtils.addMinutes(new Date(), 4));

        List<VerificationCode> codes = codeDao.selectByExample(example);
        if (CollectionUtil.isNotEmpty(codes)) {
            throw new RuntimeException("请勿频繁操作");
        }

        String randomCode = genCode(4);
        VerificationCode verificationCode = new VerificationCode();
        verificationCode.setCode(randomCode);
        verificationCode.setCountryCode(countryCode);
        verificationCode.setPhone(phone);
        verificationCode.setExpiration(DateUtils.addMinutes(new Date(), 5));
        codeDao.insertSelective(verificationCode);
        VerificationCodeDTO codeDTO = new VerificationCodeDTO();
        BeanCopyUtil.copyBean(verificationCode, codeDTO);
        return codeDTO;
    }

    @Override
    public UserDTO loginByDevice(UserParams userParams) {
        if (!MobileValidator.isValidChineseMobileNumber(userParams.getPhone())) {
            throw new RuntimeException("手机号不合法!");
        }
        UserInfo record = new UserInfo();
        record.setLastLogin(new Date());
        record.setOnlineStatus(OnlineStatus.ONLINE.getStatus());
        record.setLastAddress(userParams.getAddress());
        record.setLastDevice(userParams.getDeviceId());
        record.setPhone(userParams.getPhone());
        return  login(record, userParams.getPhone());

    }

    @Override
    public UserDTO loginByCode(String phone, String code) {
        if (checkCode(phone, code) == null) {
            throw new RuntimeException("无效验证码");
        }
        return login(new UserInfo(), phone);
    }

    @Override
    public UserDTO login(String phone) {
        return login(new UserInfo(), phone);
    }

    @Override
    public Boolean logout(String phone) {
        UserInfoExample example = new UserInfoExample();
        example.createCriteria().andPhoneEqualTo(phone);
        List<UserInfo> userInfos = userInfoDao.selectByExample(example);
        if (CollectionUtil.isNotEmpty(userInfos)) {
            UserInfo record = new UserInfo();
            record.setOnlineStatus(OnlineStatus.OFFLINE.getStatus());
            userInfoDao.updateByExampleSelective(record, example);
        } else {
            return false;
        }
        return true;
    }

    @Override
    public List<UserDTO> queryRecorderList(UserParams loginParam) {

        if (loginParam == null) {
            return null;
        }
        UserInfoExample example = new UserInfoExample();
        UserInfoExample.Criteria criteria = example.createCriteria();
        if (loginParam.getStartTime() != null && loginParam.getEndTime() != null) {
            criteria.andLastLoginBetween(loginParam.getStartTime(), loginParam.getEndTime());
        }
        if (StringUtil.isNotEmpty(loginParam.getEmployeeId())) {
            criteria.andEmployeeIdEqualTo(loginParam.getEmployeeId());
        }
        if (StringUtil.isNotEmpty(loginParam.getPhone())) {
            criteria.andPhoneEqualTo(loginParam.getPhone());
        }

        List<UserInfo> userInfos = userInfoDao.selectByExample(example);
        return userInfos.stream().map(this::convertToUserDTO).collect(Collectors.toList());
    }


    @Override
    public UserDTO queryUserInfo(String employeeId) {
        if (StringUtil.isEmpty(employeeId)) {
            return null;
        }
        UserInfoExample example = new UserInfoExample();
        UserInfoExample.Criteria criteria = example.createCriteria();
        criteria.andEmployeeIdEqualTo(employeeId);
        List<UserInfo> userInfos = userInfoDao.selectByExample(example);
        if (CollectionUtil.isNotEmpty(userInfos)) {
            return convertToUserDTO(userInfos.get(0));
        }
        return null;
    }
    @Override
    public UserDTO queryUserInfo(Long id) {

        UserInfo userInfo = userInfoDao.selectByPrimaryKey(id);
        if (userInfo != null) {
            return convertToUserDTO(userInfo);
        }
        return null;
    }

    @Override
    public List<String> querySubEmployeeList(Long userId) {
        UserDTO userDTO = queryUserInfo(userId);
        if(userDTO == null){
            throw  new RuntimeException("用户不存在");
        }
        List<String> phoneList = null;
        phoneList.add(userDTO.getPhone());
        return phoneList;
    }

    /**
     * 根据员工信息登录
     *
     * @param userParams
     * @return
     */
    @Override
    public UserDTO loginByEmpInfo(UserParams userParams) {
        UserInfo record = new UserInfo();
        record.setLastLogin(new Date());
        record.setOnlineStatus(OnlineStatus.ONLINE.getStatus());
        record.setLastAddress(userParams.getAddress());
        record.setLastDevice(userParams.getDeviceId());
//        record.setPhone(userParams.getPhone());
        return  loginByEmployeeId(record, userParams.getEmployeeId(), userParams.getPassword());
    }

    private UserDTO convertToUserDTO(UserInfo userInfo) {
        UserDTO userDTO = new UserDTO();
        BeanCopyUtil.copyBean(userInfo, userDTO);
        return userDTO;
    }

    /**
     * 产生短信验证码
     *
     * @param length
     * @return
     */
    public String genCode(int length) {
        String retStr = "";
        String strTable = "1234567890";
        int len = strTable.length();
        boolean bDone = true;
        do {
            retStr = "";
            int count = 0;
            for (int i = 0; i < length; i++) {
                double dblR = Math.random() * len;
                int intR = (int) Math.floor(dblR);
                char c = strTable.charAt(intR);
                if (('0' <= c) && (c <= '9')) {
                    count++;
                }
                retStr += strTable.charAt(intR);
            }
            if (count >= 2) {
                bDone = false;
            }
        } while (bDone);
        return retStr;
    }

    /**
     * 检查验证码
     *
     * @param phone
     * @param code
     * @return
     */
    private VerificationCode checkCode(String phone, String code) {
        VerificationCodeExample example = new VerificationCodeExample();
        VerificationCodeExample.Criteria criteria = example.createCriteria();
        criteria.andPhoneEqualTo(phone);
        criteria.andCodeEqualTo(code);
        criteria.andExpirationGreaterThan(new Date());
        List<VerificationCode> codes = codeDao.selectByExample(example);
        if (CollectionUtil.isEmpty(codes)) {
            return null;
        }
        return codes.get(0);
    }

    private UserDTO loginByEmployeeId(UserInfo record, String employeeId, String password) {
        UserDTO userDTO = new UserDTO();
        // 用工号来查询用户，适配手机号变更的场景
        UserInfoExample example = new UserInfoExample();
        example.createCriteria().andEmployeeIdEqualTo(employeeId);
        List<UserInfo> userInfos = userInfoDao.selectByExample(example);

        FetchAuthCode fetchAuthCode = FetchAuthCode.builder()
                .username(employeeId).password(password).service("").build();

        YhUserInfo yhUserInfo = YonghuiApiUtil.getUserInfoMock(fetchAuthCode, "");
//        YhUserInfo yhUserInfo = YonghuiApiUtil.getUserInfo(fetchAuthCode, "");
        if(ObjectUtil.isEmpty(yhUserInfo)){
            throw new RuntimeException("用户不存在");
        }
        if (CollectionUtil.isEmpty(userInfos)) {
            record.setLastLogin(new Date());
            //手机号
            record.setPhone(yhUserInfo.getTelephoneNumber());
            record.setType((byte)1);
            //工号
            record.setEmployeeId(yhUserInfo.getEmployeeNumber());
            record.setEmpName(yhUserInfo.getDisplayName());
            userInfoDao.insertSelective(record);
            BeanCopyUtil.copyBean(record, userDTO);
        } else {
            record = CollUtil.getFirst(userInfos);
            //更新用户信息
            //手机号
            record.setPhone(yhUserInfo.getTelephoneNumber());
            //工号
            record.setEmployeeId(yhUserInfo.getEmployeeNumber());
            //姓名
            record.setEmpName(yhUserInfo.getDisplayName());
            BeanCopyUtil.copyBean(record, userDTO);
            userInfoDao.updateByExampleSelective(record, example);
        }
        userDTO.setDownloadStatus(1);
        userDTO.setAccessToken(JwtUtil.generateAccessToken(record));
        userDTO.setRefreshToken(JwtUtil.generateRefreshToken(record));
        return userDTO;
    }
    private UserDTO login(UserInfo record, String phone) {
        UserDTO userDTO = new UserDTO();
        // 用工号来查询用户，适配手机号变更的场景
        UserInfoExample example = new UserInfoExample();
        example.createCriteria().andPhoneEqualTo(phone);
        List<UserInfo> userInfos = userInfoDao.selectByExample(example);
        if (CollectionUtil.isEmpty(userInfos)) {
            record.setPhone(phone);
            record.setType((byte)1);
            record.setEmployeeId("" + SnowFlake.getSnowId());
            record.setEmpName(randomLetterString(8));
            userInfoDao.insertSelective(record);
            BeanCopyUtil.copyBean(record, userDTO);
        } else {
            // TODO 如果接入其他账号信息，需要更新
//            userInfoDao.updateByExampleSelective(record, example);
            record = CollUtil.getFirst(userInfos);
            BeanCopyUtil.copyBean(record, userDTO);
        }
        userDTO.setDownloadStatus(1);
        userDTO.setAccessToken(JwtUtil.generateAccessToken(record));
        userDTO.setRefreshToken(JwtUtil.generateRefreshToken(record));
        return userDTO;
    }


    public static String randomLetterString(int length) {
            StringBuilder sb = new StringBuilder();
            Random random = new Random();
            String alphabets = "abcdefghijklmnopqrstuvwxyz";

            for (int i = 0; i < length; i++) {
                int index = random.nextInt(alphabets.length()); // 生成0到alphabet.length()之间的随机数
                char c = alphabets.charAt(index);
                sb.append(c);
            }

            String randomString = sb.toString();
            return randomString;
    }
}
